package com.ccp.dev.system.listener;

import com.ccp.dev.core.basic.db.datasource.DataSourceUtil;
import com.ccp.dev.core.basic.db.datasource.DynamicDataSource;
import com.ccp.dev.system.model.SysDataSource;
import com.ccp.dev.system.service.SysDataSourceService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

import javax.sql.DataSource;
import java.sql.Connection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * 扫描系统xml中配置的数据源动态加入到系统的dataSourceMap数据源中
 *
 * <pre>
 * 构建组：x5-base-db
 * 作者：ray
 * 邮箱:zhangyg@jee-soft.cn
 * 日期:2014-4-11-下午2:11:24
 * </pre>
 */
public class DataSourceInitListener implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    private SysDataSourceService sysDataSourceService;

    protected static final Logger log = LoggerFactory.getLogger(DataSourceInitListener.class);

    @Override
    public void onApplicationEvent(ContextRefreshedEvent ev) {
        // 防止重复执行。
        if (ev.getApplicationContext().getParent() == null) {
            ApplicationContext context = ev.getApplicationContext();
            // 加载配置文件中的数据源
            loadFromXml(context);
            // 加载数据库中的数据源
            loadFromDb();
            //测试连接
            connectTest();
        }
    }

    /**
     * 加载配置文件中的数据源
     *
     * @param context 应用上下文
     */
    private void loadFromXml(ApplicationContext context) {
        DynamicDataSource dynamicDataSource = (DynamicDataSource) context.getBean(DataSourceUtil.GLOBAL_DATASOURCE);

        // 加载配置文件中的数据源
        Map<String, DataSource> mapDataSource = context.getBeansOfType(DataSource.class);

        Set<Entry<String, DataSource>> dsSet = mapDataSource.entrySet();
        for (Iterator<Entry<String, DataSource>> it = dsSet.iterator(); it.hasNext(); ) {
            Entry<String, DataSource> ent = it.next();
            String key = ent.getKey();
            if (key.equals(DataSourceUtil.GLOBAL_DATASOURCE) || key.equals(DataSourceUtil.DEFAULT_DATASOURCE)) {
                continue;
            }
            try {
                dynamicDataSource.addDataSource(key, ent.getValue());
            } catch (Exception e) {
                log.debug(e.getMessage());
                e.printStackTrace();
            }
            log.debug("add dataSource " + ent.getKey());
        }
    }

    /**
     * 从数据库加载数据源
     */
    private void loadFromDb() {
        List<SysDataSource> sysDataSources = sysDataSourceService.queryListALL();
        for (SysDataSource sysDataSource : sysDataSources) {
            if (!sysDataSource.getEnabled() || !sysDataSource.getInitOnStart()) {
                continue;
            }
            try {
                DataSourceUtil.addDataSource(sysDataSource.getAlias(), sysDataSourceService.getDsFromSysSource(sysDataSource));
            } catch (Exception e) {
                log.debug("add dataSource " + sysDataSource.getAlias());
            }
        }
    }

    /**
     * 测试连接
     */
    private void connectTest() {
        log.info("目前容器里的数据源--------------->");
        Map<Object, Object> map = null;
        try {
            map = DataSourceUtil.getDataSources();
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        if (null == map) {
            return;
        }
        for (Object object : map.keySet()) {
            if (null == map.get(object)) {
                continue;
            }
            boolean isConnect = false;
            try {
                Connection connection = ((DataSource) map.get(object)).getConnection();
                connection.close();
                isConnect = true;
            } catch (Exception e) {
                log.info("alias:" + object + "--connect fail");
                e.printStackTrace();
            }
            log.info("alias:" + object + "--className:" + map.get(object).getClass().getName() + "--connectable:" + isConnect);
        }
        log.info("<----------------------");
    }

}
